# -*- coding: utf-8 -*-
"""
时间同步模块
参考项目中的TimeScaler实现，确保音视频精确同步
"""

from typing import List, Optional, Tuple
from pathlib import Path

from .subtitle_parser import SubtitleSegment, SubtitleParser


class TimeScaler:
    """
    时间同步控制器
    参考项目实现，确保音视频精确同步
    """

    def __init__(
        self,
        scene,
        audio_duration: float,
        subtitle_file: Optional[Path] = None,
        tolerance_ms: float = 100.0,
    ):
        """
        初始化TimeScaler

        Args:
            scene: Manim场景
            audio_duration: 音频时长（秒）
            subtitle_file: 字幕文件路径
            tolerance_ms: 同步容差（毫秒）
        """
        self.scene = scene
        self.audio_duration = audio_duration
        self.subtitles: List[SubtitleSegment] = []
        self.current_time = 0.0
        self.tolerance = tolerance_ms / 1000.0  # 转换为秒

        if subtitle_file and subtitle_file.exists():
            self.load_subtitles(subtitle_file)

    def load_subtitles(self, subtitle_file: Path) -> List[SubtitleSegment]:
        """
        加载字幕文件

        Args:
            subtitle_file: 字幕文件路径

        Returns:
            字幕片段列表
        """
        self.subtitles = SubtitleParser.load_srt(subtitle_file)
        return self.subtitles

    def sync_to_subtitle(self, subtitle_index: int, offset: float = 0.0) -> bool:
        """
        同步到指定字幕的起始时间

        Args:
            subtitle_index: 字幕索引（1-based）
            offset: 偏移量（秒）

        Returns:
            是否成功同步
        """
        if not (1 <= subtitle_index <= len(self.subtitles)):
            print(f"Warning: Invalid subtitle index {subtitle_index}")
            return False

        target_time = self.subtitles[subtitle_index - 1].start_time + offset
        elapsed = self.current_time

        if target_time > elapsed + self.tolerance:
            # 需要等待
            wait_time = target_time - elapsed
            self.scene.wait(wait_time)
            self.current_time = target_time
            return True
        elif target_time < elapsed - self.tolerance:
            # 已经超前
            print(
                f"Warning: Target time {target_time:.3f}s is before current time "
                f"{elapsed:.3f}s (subtitle {subtitle_index})"
            )
            return False
        else:
            # 在容差范围内，认为已经同步
            self.current_time = max(self.current_time, target_time)
            return True

    def wait_for_subtitle_duration(self, subtitle_index: int, fraction: float = 1.0) -> float:
        """
        等待指定字幕的时长

        Args:
            subtitle_index: 字幕索引（1-based）
            fraction: 时长比例

        Returns:
            实际等待时间
        """
        if not (1 <= subtitle_index <= len(self.subtitles)):
            return 0.0

        subtitle = self.subtitles[subtitle_index - 1]
        duration = subtitle.duration * fraction
        self.scene.wait(duration)
        self.current_time += duration
        return duration

    def ensure_alignment(self, target_duration: float, buffer: float = 0.3) -> float:
        """
        确保动画与音频对齐

        Args:
            target_duration: 目标时长
            buffer: 缓冲时间

        Returns:
            实际等待时间
        """
        remaining = self.audio_duration - self.current_time
        if remaining > buffer:
            wait_time = remaining - buffer
            self.scene.wait(wait_time)
            self.current_time += wait_time
            return wait_time
        return 0.0

    def sync_to_next_subtitle(self, offset: float = 0.0) -> Optional[int]:
        """
        同步到下一个字幕

        Args:
            offset: 偏移量（秒）

        Returns:
            同步到的字幕索引，如果失败返回None
        """
        # 找到当前时间对应的字幕
        current_index = None
        for i, subtitle in enumerate(self.subtitles):
            if subtitle.start_time <= self.current_time < subtitle.end_time:
                current_index = i
                break

        # 找到下一个字幕
        next_index = (current_index + 1 if current_index is not None else 0) + 1
        if next_index <= len(self.subtitles):
            if self.sync_to_subtitle(next_index, offset):
                return next_index

        return None

    def wait_until_subtitle_end(self, subtitle_index: int) -> float:
        """
        等待到指定字幕结束

        Args:
            subtitle_index: 字幕索引（1-based）

        Returns:
            等待时间
        """
        if not (1 <= subtitle_index <= len(self.subtitles)):
            return 0.0

        subtitle = self.subtitles[subtitle_index - 1]
        if self.current_time < subtitle.end_time:
            wait_time = subtitle.end_time - self.current_time
            self.scene.wait(wait_time)
            self.current_time = subtitle.end_time
            return wait_time
        return 0.0

    def get_current_subtitle(self) -> Optional[SubtitleSegment]:
        """
        获取当前时间对应的字幕

        Returns:
            当前字幕片段，如果不存在返回None
        """
        for subtitle in self.subtitles:
            if subtitle.start_time <= self.current_time < subtitle.end_time:
                return subtitle
        return None

    def get_next_subtitle(self) -> Optional[SubtitleSegment]:
        """
        获取下一个字幕

        Returns:
            下一个字幕片段，如果不存在返回None
        """
        for subtitle in self.subtitles:
            if subtitle.start_time > self.current_time:
                return subtitle
        return None

    def check_sync_accuracy(self) -> dict:
        """
        检查同步精度

        Returns:
            同步精度报告
        """
        if not self.subtitles:
            return {"status": "no_subtitles"}

        issues = []
        warnings = []

        # 检查是否有字幕在当前时间之后
        upcoming = [s for s in self.subtitles if s.start_time > self.current_time]
        if not upcoming:
            warnings.append("No upcoming subtitles")

        # 检查时间轴
        gaps = []
        overlaps = []

        for i in range(len(self.subtitles) - 1):
            current = self.subtitles[i]
            next_sub = self.subtitles[i + 1]
            gap = next_sub.start_time - current.end_time

            if gap < -self.tolerance:
                overlaps.append(
                    {
                        "subtitle1": current.index,
                        "subtitle2": next_sub.index,
                        "overlap": -gap,
                    }
                )
            elif gap > 1.0:
                gaps.append(
                    {
                        "after": current.index,
                        "before": next_sub.index,
                        "duration": gap,
                    }
                )

        status = "good"
        if overlaps:
            status = "poor"
        elif gaps:
            status = "fair"

        return {
            "status": status,
            "total_subtitles": len(self.subtitles),
            "current_time": self.current_time,
            "audio_duration": self.audio_duration,
            "gaps": gaps,
            "overlaps": overlaps,
            "warnings": warnings,
        }

    def auto_sync_sequence(self, start_subtitle: int = 1) -> dict:
        """
        自动同步序列 - 为整个场景生成时间同步代码

        Args:
            start_subtitle: 起始字幕索引

        Returns:
            同步代码生成结果
        """
        code_lines = [
            "# 自动生成的同步代码",
            f"scaler = TimeScaler(self, {self.audio_duration:.3f})",
        ]

        synced_count = 0
        failed_count = 0

        # 从指定字幕开始同步
        for i in range(start_subtitle - 1, len(self.subtitles)):
            subtitle = self.subtitles[i]
            code_lines.append(f"# 字幕 {subtitle.index}: {subtitle.text[:30]}...")
            code_lines.append(f"scaler.sync_to_subtitle({subtitle.index})")
            code_lines.append(f"# 等待 {subtitle.duration:.3f} 秒")
            code_lines.append(f"scaler.wait_for_subtitle_duration({subtitle.index})")
            synced_count += 1

        # 添加对齐代码
        code_lines.append("# 确保对齐")
        code_lines.append("scaler.ensure_alignment(target_duration=1.5)")

        return {
            "code": "\n".join(code_lines),
            "synced_count": synced_count,
            "failed_count": failed_count,
            "total_duration": self.audio_duration,
        }
